package com.cyberypower.sjs.socket2jabber;

import com.cyberypower.sjs.common.Config;
import com.cyberypower.sjs.jabber.JabberAddress;
import com.cyberypower.sjs.jabber.JabberClientSocket;
import com.cyberypower.sjs.jabber.JabberServerSocket;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.Vector;

public class MultiSocketServer {


    class ServeOneJabber extends Thread {

        private Socket socket;
        private InputStream in;
        private OutputStream out;
        private JabberClientSocket jcs;

        private Logger log = Logger.getLogger(this.getClass());

        public ServeOneJabber(Socket s, JabberAddress j2sAddress)
                throws IOException {
            socket = s;
            if (socket != null)
                log.info("accepted SOCKET connection from " + socket.getRemoteSocketAddress());
            else log.error("null socket");
            in =
                    socket.getInputStream();
            out =
                    socket.getOutputStream();

            jcs = jss.connect(j2sAddress);
            jcs.setOutput(out);

            start();
        }

        public void run() {
            jcs.sendText(Config.INIT_CHAT);
            synchronized (jcs.getFlag()) {
                jcs.setPleaseWait(true);
                while (jcs.isPleaseWait()) {
                    try {
                        jcs.getFlag().wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            try {
                final byte[] buf = new byte[Config.BUFFER_SIZE];
                while (true) {
                    final int len = in.read(buf);
                    if (len == -1) {
                        break;
                    }
                    jcs.send(ByteBuffer.wrap(buf, 0, len));
                    if (jcs.isHas_to_close())
                        break;
                }
            } catch (Exception e) {
                log.warn(e);
            } finally {
                try {
                    socket.close();
                } catch (IOException e) {
                    log.warn(e);
                }
            }
        }
    }


    private int port;
    private JabberAddress j2sAddress;
    private JabberAddress s2jAddress;
    private JabberServerSocket jss;
    static Vector<ServeOneJabber> serveOneJabbers = new Vector<ServeOneJabber>();

    private Logger log = Logger.getLogger(this.getClass());

    public MultiSocketServer(JabberAddress s2jAddress, JabberAddress j2sAddress, int port) {
        this.port = port;
        this.s2jAddress = s2jAddress;
        this.j2sAddress = j2sAddress;
    }

    public void emph() throws Exception {
        ServerSocket serverSocket = new ServerSocket(port);
        log.info("Socket Server started : " + port);
        jss = new JabberServerSocket(s2jAddress);

        try {
            while (true) {
                Socket socket = serverSocket.accept();
                try {
                    serveOneJabbers.add(new ServeOneJabber(socket, j2sAddress));
                } catch (IOException e) {
                    log.warn(e);
                    socket.close();
                }
            }
        } finally {
            serverSocket.close();
        }
    }


}